<?php

/**
 * QPHP
 *
 * Copyright (c) 2022 QPHP
 *
 * @author lbnnbs
 * @copyright Copyright (c) 2022 lbnnbs QPHP (https://gitee.com/lbnnbs/qphp)
 * @license AGPLv3 License
 */
class Verifier {
    
    static public function isEmail($string) {
        return preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([_a-z0-9]+\.)+[a-z]{2,5}$/', $string);
    }
    
    /**
     * 数字（没有小数点）
     *
     * @param $string
     * @return false|int
     */
    static public function isNumeric($string) {
        return preg_match('/^[0-9]+$/', $string);
    }
    
    /**
     * 固定电话号码
     *
     * @param $string
     * @return false|int
     */
    static public function isPhone($string) {
        return preg_match('/^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/', $string);
    }
    
    /**
     * 手机号码
     *
     * @param $string
     * @return false|int
     */
    static public function isMobile($string) {
        return preg_match('/^((\(\d{2,3}\))|(\d{3}\-))?1[3|4|5|6|7|8|9]\d{9}$/', $string);
    }
    
    /**
     * 电话号码（含固定电话号码和手机号码）
     *
     * @param $string
     * @return false|int
     */
    static public function isMobilePhone($string) {
        return preg_match('/(^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,12}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}1[3|4|5|6|7|8|9][0-9]{9}$)/', $string);
    }
    
    /**
     * 中文
     *
     * @param $string
     * @return false|int
     */
    static public function isChina($string) {
        return preg_match('/^[\x7f-\xff]+$/', $string);
    }
    
    /**
     * 含有中文
     *
     * @param $string
     * @return false|int
     */
    static public function hasChina($string) {
        return preg_match('/[\x7f-\xff]/', $string);
    }
    
    /**
     * URL地址
     *
     * @param $string
     * @return false|int
     */
    static public function isUrl($string) {
        return preg_match('/[a-zA-Z]+:\/\/[^\s]*/', $string);
    }
    
    /**
     * IP地址
     *
     * @param $string
     * @return false|int
     */
    static public function isIpAddr($string) {
        return preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $string);
    }
    
    /**
     * 邮编
     *
     * @param $string
     * @return false|int
     */
    static public function isZip($string) {
        return preg_match('/^[1-9]\d{5}$/', $string);
    }
    
    /**
     * 仅字母数字下划线
     *
     * @param $string
     * @return false|int
     */
    static public function isWord($string) {
        return preg_match('/[a-zA-Z0-9_]$/', $string);
    }
    
    /**
     * 24小时制时间
     *
     * @param $string
     * @return false|int
     */
    static public function isTime($string) {
        
        if (preg_match('/^(\d{2}):(\d{2})$/', $string, $match)) {
            if (isset($match[1]) && intval($match[1]) < 24 && intval($match[1]) > -1
                && isset($match[2]) && intval($match[2]) < 60 && intval($match[2]) > -1) {
                return true;
            }
        }
        
        if (preg_match('/^(\d{2}):(\d{2}):(\d{2})$/', $string, $match)) {
            if (isset($match[1]) && intval($match[1]) < 24 && intval($match[1]) > -1
                && isset($match[2]) && intval($match[2]) < 60 && intval($match[2]) > -1
                && isset($match[3]) && intval($match[3]) < 60 && intval($match[3]) > -1) {
                return true;
            }
        }
        
        return false;
    }
    
    static public function isDate($string) {
        
        if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $string, $match)) {
            return false;
        }
        
        if (!isset($match[1]) || !isset($match[2]) || !isset($match[3])) {
            return false;
        }
        
        $year = intval($match[1]);
        $month = intval($match[2]);
        $day = intval($match[3]);
        
        if ($year < 1970 || $month < 1 || $day < 1) {
            return false;
        }
        
        if ($year > 9999 || $month > 12) {
            return false;
        }
        
        if ($month === 1 || $month === 3 || $month === 5 || $month === 7 ||
            $month === 8 || $month === 10 || $month === 12) {
            $days = 31;
        } else if ($month === 4 || $month === 6 || $month === 9 || $month === 11) {
            $days = 30;
        } else if ($month === 2) {
            if ($year % 4 === 0 && ($year % 100 !== 0 || $year % 400 === 0)) { // 闰年
                $days = 29;
            } else {
                $days = 28;
            }
        }
        
        if ($day > $days) {
            return false;
        }
        
        return true;
    }
    
    static public function isDatetime($string) {
        
        if (!preg_match('/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}(:\d{2})?)$/', $string, $match)) {
            return false;
        }
        
        if (!isset($match[1])) {
            return false;
        }
        
        if (!isset($match[2])) {
            return false;
        }
        
        if (!static::isDate($match[1])) {
            return false;
        }
        
        if (!static::isTime($match[2])) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 港澳台身份证
     *
     * @param $idcard
     * @return bool
     */
    static public function validGOTID($idcard) {
        $idcard = strtoupper($idcard);
        $idcard = str_replace(array('（', '）'), array('(', ')'), $idcard);
        preg_match('/^([A-Z])([0-9]{6})\(([A0-9]{1})\)$/', $idcard, $match);//香港
        if ($match && count($match) == 4) {
            $sum = (ord($match[1]) - 64) * 8;
            $index = 7;
            for ($j = 0; $j < 6; $j++) {
                $sum += $match[2][$j] * $index;
                $index--;
            }
            $get_num = $sum % 11;
            if ($get_num == 1) $get_num = 'A';
            elseif ($get_num > 1) $get_num = 11 - $get_num;
            
            if ($match[3] == $get_num) return true;
            return false;
        }
        preg_match('/^([A-Z])([0-9]{9})$/', $idcard, $taiwan);//中国台湾省
        if ($taiwan && count($taiwan) == 3)//首位数字代表性别，男性为1、女性为2
        {
            $area_code = array(
                'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13,
                'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 34,
                'J' => 18, 'K' => 19, 'L' => 20, 'M' => 21, 'N' => 22,
                'O' => 35, 'P' => 23, 'Q' => 24, 'R' => 25, 'S' => 26,
                'T' => 27, 'U' => 28, 'V' => 29, 'W' => 32, 'X' => 30,
                'Y' => 31, 'Z' => 33);
            $code = strval($area_code[$taiwan[1]]);
            $sum = intval($code[0]) + intval($code[1]) * 9;
            $index = 8;
            for ($k = 0; $k < 8; $k++) {
                $sum += intval($taiwan[2][$k]) * $index;
                $index--;
            }
            $get_num = 10 - $sum % 10;
            if ($get_num == $taiwan[2][8]) return true;
            return false;
        }
        preg_match('/^[157][0-9]{6}\([0-9]\)$/', $idcard, $aomen); // 澳门
        if ($aomen) {
            return true;
        }
        return false;
    }
    
    /**
     * 中国身份证
     *
     * @param $idcard
     * @return bool
     */
    static public function validIDCard($idcard) {
        $vCity = array(
            '11', '12', '13', '14', '15', '21', '22',
            '23', '31', '32', '33', '34', '35', '36',
            '37', '41', '42', '43', '44', '45', '46',
            '50', '51', '52', '53', '54', '61', '62',
            '63', '64', '65', '71', '81', '82', '91'
        );
        
        if (!preg_match('/^([\d]{17}[xX\d]|[\d]{15})$/', $idcard))
            return false;
        
        if (!in_array(substr($idcard, 0, 2), $vCity))
            return false;
        
        $idcard = preg_replace('/[xX]$/i', 'a', $idcard);
        $vLength = strlen($idcard);
        
        if ($vLength == 18) {
            $vBirthday = substr($idcard, 6, 4) . '-' . substr($idcard, 10, 2) . '-' . substr($idcard, 12, 2);
        } else {
            $vBirthday = '19' . substr($idcard, 6, 2) . '-' . substr($idcard, 8, 2) . '-' . substr($idcard, 10, 2);
        }
        
        if (date('Y-m-d', strtotime($vBirthday)) != $vBirthday)
            return false;
        if ($vLength == 18) {
            $vSum = 0;
            
            for ($i = 17; $i >= 0; $i--) {
                $vSubStr = substr($idcard, 17 - $i, 1);
                $vSum += (pow(2, $i) % 11) * (($vSubStr == 'a') ? 10 : intval($vSubStr, 11));
            }
            
            if ($vSum % 11 != 1)
                return false;
        }
        
        return true;
    }
    
}
